using DapperExtensionsNew.Configuration;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace DapperExtensionsNew.Queryable.Analyzers
{
	public class Equal : Where
	{
		private static readonly Type[] Types = new Type[7]
		{
			typeof(int),
			typeof(decimal),
			typeof(string),
			typeof(DateTime),
			typeof(bool),
			typeof(long),
			typeof(Guid)
		};

		protected override bool IsSatisfied(Context context, PropertyInfo queryProperty)
		{
			Type propertyType = queryProperty.PropertyType;
			PropertyInfo propertyInfo = context.ModelProperties.FirstOrDefault((PropertyInfo x) => x.Name == queryProperty.Name);
			if (propertyInfo == null)
			{
				return false;
			}
			Type propertyType2 = propertyInfo.PropertyType;
			if (Types.Contains(propertyType))
			{
				if (propertyType2.IsGenericType && propertyType2.GetGenericTypeDefinition() == typeof(Nullable<>))
				{
					return propertyType == propertyType2.GetGenericArguments().First();
				}
				return propertyType == propertyInfo.PropertyType;
			}
			if (!propertyType.IsGenericType || !(propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
			{
				return false;
			}
			Type type = propertyType.GetGenericArguments().First();
			if (!Types.Contains(type))
			{
				return false;
			}
			if (propertyType2.IsGenericType && propertyType2.GetGenericTypeDefinition() == typeof(Nullable<>))
			{
				return type == propertyType2.GetGenericArguments().First();
			}
			return type == propertyType2;
		}

		protected override Expression GetWhereClause(Context context, PropertyInfo queryProperty)
		{
			string name = queryProperty.Name;
			string columnName = GetColumnName(context.ModelType, name);
			Type propertyType = queryProperty.PropertyType;
			MemberExpression memberExpression = Expression.Property(context.QueryExpression, queryProperty);
			SqlDatabaseOptions sqlDatabaseOptions = SqlDatabaseOptionsFactory.GetSqlDatabaseOptions(context.Analyzer);
			string startDelimiter = sqlDatabaseOptions.StartDelimiter;
			string endDelimiter = sqlDatabaseOptions.EndDelimiter;
			ConstantExpression left = Expression.Constant(" AND " + startDelimiter + columnName + endDelimiter + " = ");
			Expression expression = Expression.Constant("@" + columnName);
			Expression stringParam = ConcatExpression(left, expression);
			BlockExpression blockExpression = Expression.Block(CallStringBuilderAppend(context.SqlExpression, stringParam), CallAddParameters(context.ParametersExpression, expression, memberExpression));
			if (propertyType == typeof(string) || propertyType.IsGenericType)
			{
				return Expression.IfThen(Expression.NotEqual(memberExpression, Expression.Constant(null)), blockExpression);
			}
			return blockExpression;
		}
	}
}
